//
//  NSObject+Runtime.m
//  objc_property_t 的使用
//
//  Created by dllo on 16/7/15.
//  Copyright © 2016年 dllo. All rights reserved.
//

#import "NSObject+Runtime.h"
#import <objc/runtime.h>

@implementation NSObject (Runtime)

/**
 * iOS反射机制：objc_property_t
 * 常用于字典数据解析
 * 将两个对象的所有属性，用动态的方式取出来，并根据属性名自动绑定值
 **/

/** 数据在这里解析 */
- (NSArray *)propertyKeys
{
    unsigned int outCount;
    // 选择对哪个类进行反射,outCount中会存放你定义属性的个数
    // 返回值properties 是一个结构体指针
    // 它还可以用 struct objc_property **properties 表示
    objc_property_t *properties = class_copyPropertyList([self class], &outCount);
    
    // 定义一个数组,用来接收属性的名字
    NSMutableArray *keys = [NSMutableArray array];
    for (int i = 0; i < outCount; i++) {
        
        // 通过properties结构体指针得到objc_property_t型的结构体变量,这个结构体的名字是你要的属性名
        objc_property_t property = properties[i];
        
        // 将C字符串(变量名)转化为oc字符串对象
        NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        
        
        [keys addObject:propertyName];
    }
    
    // 将C的指针释放
    free(properties);
    
    // 添加所有的父类属性，直到命中NSObject
//    
//    NSString *superClassName = [NSString stringWithUTF8String:class_getName([self class])];
//    if (![superClassName isEqualToString:@"NSObject"]) {
//        keys = [NSMutableArray array];
//        for (NSString *property in [[self superclass] propertyKeys]) {
//            [keys addObject:property];
//        }
//    }
//    NSLog(@"%@", keys);
    return keys;
}

/** 是否从另一个对象中反射数据 */
- (BOOL)reflectDataFromOtherObject:(NSDictionary *)dic
{
    BOOL ret = NO;
    for (NSString *key in [self propertyKeys]) {
//        if ([dic isKindOfClass:[NSDictionary class]]) {
//            ret = ([dic valueForKey:key] == nil) ? NO: YES;
//        } else {
//            ret = [dic respondsToSelector:NSSelectorFromString(key)];
//        }
//        if (ret) {
            id propertyValue = [dic valueForKey:key];
            if (![propertyValue isKindOfClass:[NSNull class]] && propertyValue !=nil) {
                [self setValue:propertyValue forKey:key];
//            }
        }
    }
    
    
    return ret;
}

@end
